<!--
  智慧小区管理系统 - 图表组件
  @author Wu.Liang
  @date 2024-01-01
-->
<template>
    <div ref="chartRef" :style="{ width: '100%', height: height }"></div>
</template>

<script setup lang="ts">
/**
 * Chart图表组件
 * @author Wu.Liang
 * @date 2024-01-01
 */
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
import * as echarts from 'echarts'

interface Props {
    type: 'line' | 'bar' | 'pie' | 'doughnut' | 'area'
    data: any
    options?: any
    height?: string
    width?: string
}

const props = withDefaults(defineProps<Props>(), {
    height: '400px',
    width: '100%',
    options: () => ({})
})

const chartRef = ref<HTMLElement>()
let chartInstance: echarts.ECharts | null = null

/**
 * 初始化图表
 */
const initChart = async () => {
    await nextTick()

    try {
        if (!chartRef.value || !document.contains(chartRef.value)) {
            console.warn('Chart组件DOM元素未准备好，跳过初始化')
            return
        }

        // 销毁已存在的实例
        if (chartInstance) {
            chartInstance.dispose()
        }

        // 创建新实例
        chartInstance = echarts.init(chartRef.value)

        // 设置图表配置
        const chartOptions = getChartOptions()
        chartInstance.setOption(chartOptions)

        // 监听窗口大小变化
        window.addEventListener('resize', handleResize)
    } catch (error) {
        if (error instanceof Error && 
            (error.message.includes('getAttribute') || 
             error.message.includes('getBoundingClientRect'))) {
            console.warn('Chart组件初始化失败，DOM元素未准备好')
            return
        }
        throw error
    }
}

/**
 * 获取图表配置
 */
const getChartOptions = () => {
    const baseOptions = {
        title: {
            text: props.options.title || '',
            left: 'center',
            textStyle: {
                fontSize: 16,
                fontWeight: 'normal',
                color: '#303133'
            }
        },
        tooltip: {
            trigger: 'axis',
            backgroundColor: 'rgba(0, 0, 0, 0.8)',
            borderWidth: 0,
            textStyle: {
                color: '#fff'
            }
        },
        legend: {
            top: 'top',
            left: 'center',
            orient: 'horizontal',
            textStyle: {
                color: '#606266'
            }
        },
        grid: {
            top: '15%',
            left: '3%',
            right: '4%',
            bottom: '10%',
            containLabel: true
        },
        color: ['#409eff', '#67c23a', '#e6a23c', '#f56c6c', '#909399'],
        ...props.options
    }

    switch (props.type) {
    case 'line':
        return getLineChartOptions(baseOptions)
    case 'bar':
        return getBarChartOptions(baseOptions)
    case 'pie':
    case 'doughnut':
        return getPieChartOptions(baseOptions)
    case 'area':
        return getAreaChartOptions(baseOptions)
    default:
        return baseOptions
    }
}

/**
 * 折线图配置
 */
const getLineChartOptions = (baseOptions: any) => {
    return {
        ...baseOptions,
        xAxis: {
            type: 'category',
            data: props.data.labels || [],
            axisLine: {
                lineStyle: {
                    color: '#e4e7ed'
                }
            },
            axisLabel: {
                color: '#909399'
            }
        },
        yAxis: {
            type: 'value',
            axisLine: {
                show: false
            },
            axisTick: {
                show: false
            },
            axisLabel: {
                color: '#909399'
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f2f5'
                }
            }
        },
        series: (props.data.datasets || []).map((dataset: any) => ({
            name: dataset.label,
            type: 'line',
            data: dataset.data,
            smooth: true,
            symbol: 'circle',
            symbolSize: 6,
            lineStyle: {
                width: 3
            },
            areaStyle: dataset.fill ? {
                opacity: 0.1
            } : null
        }))
    }
}

/**
 * 柱状图配置
 */
const getBarChartOptions = (baseOptions: any) => {
    return {
        ...baseOptions,
        xAxis: {
            type: 'category',
            data: props.data.labels || [],
            axisLine: {
                lineStyle: {
                    color: '#e4e7ed'
                }
            },
            axisLabel: {
                color: '#909399'
            }
        },
        yAxis: {
            type: 'value',
            axisLine: {
                show: false
            },
            axisTick: {
                show: false
            },
            axisLabel: {
                color: '#909399'
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f2f5'
                }
            }
        },
        series: (props.data.datasets || []).map((dataset: any) => ({
            name: dataset.label,
            type: 'bar',
            data: dataset.data,
            barWidth: '60%',
            itemStyle: {
                borderRadius: [4, 4, 0, 0]
            }
        }))
    }
}

/**
 * 饼图/环形图配置
 */
const getPieChartOptions = (baseOptions: any) => {
    const seriesData = (props.data.labels || []).map((label: string, index: number) => ({
        name: label,
        value: props.data.datasets[0]?.data[index] || 0
    }))

    return {
        ...baseOptions,
        tooltip: {
            trigger: 'item',
            formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        series: [
            {
                name: props.data.datasets[0]?.label || '数据',
                type: 'pie',
                radius: props.type === 'doughnut' ? ['40%', '70%'] : '70%',
                center: ['50%', '50%'],
                data: seriesData,
                emphasis: {
                    itemStyle: {
                        shadowBlur: 10,
                        shadowOffsetX: 0,
                        shadowColor: 'rgba(0, 0, 0, 0.5)'
                    }
                },
                label: {
                    show: true,
                    formatter: '{b}: {d}%'
                },
                labelLine: {
                    show: true
                }
            }
        ]
    }
}

/**
 * 面积图配置
 */
const getAreaChartOptions = (baseOptions: any) => {
    return {
        ...baseOptions,
        xAxis: {
            type: 'category',
            data: props.data.labels || [],
            axisLine: {
                lineStyle: {
                    color: '#e4e7ed'
                }
            },
            axisLabel: {
                color: '#909399'
            }
        },
        yAxis: {
            type: 'value',
            axisLine: {
                show: false
            },
            axisTick: {
                show: false
            },
            axisLabel: {
                color: '#909399'
            },
            splitLine: {
                lineStyle: {
                    color: '#f0f2f5'
                }
            }
        },
        series: (props.data.datasets || []).map((dataset: any) => ({
            name: dataset.label,
            type: 'line',
            data: dataset.data,
            smooth: true,
            symbol: 'none',
            areaStyle: {
                opacity: 0.3
            },
            lineStyle: {
                width: 2
            }
        }))
    }
}

/**
 * 处理窗口大小变化
 */
const handleResize = () => {
    try {
        if (chartInstance && !chartInstance.isDisposed()) {
            chartInstance.resize()
        }
    } catch (error) {
        if (error instanceof Error && 
            (error.message.includes('getAttribute') || 
             error.message.includes('getBoundingClientRect'))) {
            console.warn('Chart组件resize操作跳过，DOM元素未准备好')
            return
        }
        throw error
    }
}

/**
 * 更新图表数据
 */
const updateChart = () => {
    try {
        if (chartInstance && !chartInstance.isDisposed()) {
            const chartOptions = getChartOptions()
            chartInstance.setOption(chartOptions, true)
        }
    } catch (error) {
        if (error instanceof Error && 
            (error.message.includes('getAttribute') || 
             error.message.includes('getBoundingClientRect'))) {
            console.warn('Chart组件更新操作跳过，DOM元素未准备好')
            return
        }
        throw error
    }
}

// 监听数据变化
watch(() => [props.data, props.options], () => {
    updateChart()
}, { deep: true })

// 监听类型变化
watch(() => props.type, () => {
    initChart()
})

onMounted(() => {
    initChart()
})

onUnmounted(() => {
    if (chartInstance) {
        chartInstance.dispose()
        chartInstance = null
    }
    window.removeEventListener('resize', handleResize)
})

// 暴露方法供父组件调用
defineExpose({
    updateChart,
    resize: handleResize,
    getInstance: () => chartInstance
})
</script>

<style lang="scss" scoped>
// Chart组件不需要特殊样式，ECharts会自动处理</style>
